home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
intuisup.lha
/
Intuisup
/
source.lha
/
Files
/
files.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-11
|
11KB
|
453 lines
/* $Revision Header *** Header built automatically - do not edit! ***********
*
* (C) Copyright 1991 by Torsten Jürgeleit
*
* Name .....: files.c
* Created ..: Thursday 19-Dec-91 20:00:48
* Revision .: 0
*
* Date Author Comment
* ========= ==================== ====================
* 11-Apr-92 Torsten Jürgeleit corrected abort if line too long
* 19-Dec-91 Torsten Jürgeleit Created this file!
*
****************************************************************************
*
* Support routines for reading and parsing text files
*
* $Revision Header ********************************************************/
/* Includes */
#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <libraries/diskfont.h>
#include <intuition/intuition.h>
#ifdef AZTEC_C
#include <functions.h> /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
#endif
#include <libraries/memwatch.h> /* header file for memory debug link library (Fish 240) - AFTER functions.h */
#include <string.h>
#include "/render/render.h"
#include "files.h"
/* Defines for internal flags */
#define TEXT_FILE_FLAG_READ_NEXT_LINE (1 << 15) /* if current line is empty or continued then read next line too */
/* Static prototypes */
SHORT fill_read_buffer(struct FileData *fd);
BPTR dos_open(BYTE *name, LONG flags);
LONG dos_read(BPTR fh, BYTE *buffer, LONG size);
VOID dos_close(BPTR fh);
/* Static pragmas */
#pragma regcall(fill_read_buffer(a0))
#pragma regcall(dos_open(a0,d0))
#pragma regcall(dos_read(a0,a1,d0))
#pragma regcall(dos_close(a0))
/* Open text file */
struct FileData *
open_text_file(BYTE *name, USHORT read_buffer_size, USHORT line_buffer_size,
USHORT flags)
{
struct FileData *fd = NULL;
if (name && read_buffer_size && line_buffer_size) {
BPTR fh;
if (fh = dos_open(name, (LONG)MODE_OLDFILE)) {
if (!(fd = AllocMem((LONG)(sizeof(struct FileData) +
read_buffer_size + line_buffer_size + 1),
(LONG)MEMF_PUBLIC))) {
dos_close(fh);
} else {
/* Init internal file data */
fd->fd_Name = name;
fd->fd_ReadBufferSize = read_buffer_size;
fd->fd_LineBufferSize = line_buffer_size;
fd->fd_Flags = flags;
fd->fd_FileHandle = fh;
fd->fd_ReadBuffer = (BYTE *)(fd + 1);
fd->fd_CurrentPtr = NULL;
fd->fd_LineBuffer = fd->fd_ReadBuffer + read_buffer_size;
fd->fd_ID = ISUP_ID;
/* Init public file data struct */
fd->fd_Line = NULL;
fd->fd_LineLen = 0;
fd->fd_LineNum = 0;
}
}
}
return(fd);
}
/* Read line from text file */
SHORT
read_text_line(struct FileData *fd)
{
SHORT status = TEXT_FILE_STATUS_NORMAL;
if (!fd || fd->fd_ID != ISUP_ID) {
status = TEXT_FILE_ERROR_NO_FILE_DATA;
} else {
BYTE *line = fd->fd_LineBuffer;
USHORT flags = fd->fd_Flags, len = 0;
do {
BYTE c, *ptr;
/* Fill read buffer */
if (!(ptr = fd->fd_CurrentPtr) || ptr >= fd->fd_EndPtr) {
if ((status = fill_read_buffer(fd)) == TEXT_FILE_STATUS_NORMAL) {
ptr = fd->fd_CurrentPtr;
}
}
if (status == TEXT_FILE_STATUS_NORMAL) {
/* Strip leading white space */
if (flags & TEXT_FILE_FLAG_TRIM_LINE) {
while ((c = *ptr) == ' ' || c == '\t') {
if (++ptr >= fd->fd_EndPtr) {
if ((status = fill_read_buffer(fd)) !=
TEXT_FILE_STATUS_NORMAL) {
break;
} else {
ptr = fd->fd_CurrentPtr;
}
}
}
}
if (status == TEXT_FILE_STATUS_NORMAL) {
/* Copy line from read buffer to line buffer */
if (flags & TEXT_FILE_FLAG_SKIP_COMMENTS) {
BOOL comment = FALSE;
/* Copy without comments */
while ((c = *ptr) != '\n' || comment == TRUE) {
/* Write char to line buffer */
if (comment == FALSE) {
if (len >= fd->fd_LineBufferSize) {
status = TEXT_FILE_ERROR_LINE_TOO_LONG;
break;
} else {
*line++ = c;
len++;
}
}
/* Increment ptr and fill read buffer if neccessary */
if (++ptr == fd->fd_EndPtr) {
if ((status = fill_read_buffer(fd)) !=
TEXT_FILE_STATUS_NORMAL) {
break;
} else {
ptr = fd->fd_CurrentPtr;
}
}
/* Check for comment delimiters */
if (comment == FALSE) {
if (c == '/' && *ptr == '*') {
comment = TRUE;
/* Remove '/' from line */
line--;
len--;
}
} else {
if (c == '\n') {
fd->fd_LineNum++;
} else {
if (c == '*' && *ptr == '/') {
comment = FALSE;
/* Skip '/' */
if (++ptr == fd->fd_EndPtr) {
if ((status = fill_read_buffer(fd)) !=
TEXT_FILE_STATUS_NORMAL) {
break;
} else {
ptr = fd->fd_CurrentPtr;
}
}
}
}
}
}
} else {
/* Copy with comments */
while ((c = *ptr) != '\n') {
/* Write char to line buffer */
if (len >= fd->fd_LineBufferSize) {
status = TEXT_FILE_ERROR_LINE_TOO_LONG;
break;
} else {
*line++ = c;
len++;
/* Increment ptr and fill read buffer if neccessary */
if (++ptr == fd->fd_EndPtr) {
if ((status = fill_read_buffer(fd)) !=
TEXT_FILE_STATUS_NORMAL) {
break;
} else {
ptr = fd->fd_CurrentPtr;
}
}
}
}
}
if (status == TEXT_FILE_STATUS_NORMAL) {
/* Strip trailing white space */
if (flags & TEXT_FILE_FLAG_TRIM_LINE) {
while (len && ((c = *(line - 1)) == ' ' || c == '\t')) {
line--;
len--;
}
}
if (!len) {
/* Check for skip empty line */
if (flags & TEXT_FILE_FLAG_SKIP_EMPTY_LINES) {
flags |= TEXT_FILE_FLAG_READ_NEXT_LINE;
} else {
flags &= ~TEXT_FILE_FLAG_READ_NEXT_LINE;
}
} else {
/* Check for line continuation - last char is '\'? */
if (flags & TEXT_FILE_FLAG_LINE_CONTINUATION) {
if (*(line - 1) == '\\') {
flags |= TEXT_FILE_FLAG_READ_NEXT_LINE;
/* Strip '\' from end of line */
line--;
len--;
} else {
flags &= ~TEXT_FILE_FLAG_READ_NEXT_LINE;
}
} else {
flags &= ~TEXT_FILE_FLAG_READ_NEXT_LINE;
}
}
/* Mark end of string */
*line = '\0';
fd->fd_CurrentPtr = ptr + 1; /* skip trailing '\n' */
fd->fd_LineNum++;
}
}
}
} while (status == TEXT_FILE_STATUS_NORMAL &&
(flags & TEXT_FILE_FLAG_READ_NEXT_LINE));
/* Init public data */
if (status == TEXT_FILE_STATUS_NORMAL) {
fd->fd_Line = fd->fd_LineBuffer;
fd->fd_LineLen = len;
} else {
fd->fd_Line = NULL;
fd->fd_LineLen = 0;
}
}
return(status);
}
/* Fill read buffer from text file */
STATIC SHORT
fill_read_buffer(struct FileData *fd)
{
LONG len;
SHORT status;
if ((len = dos_read(fd->fd_FileHandle, fd->fd_ReadBuffer, (LONG)
fd->fd_ReadBufferSize)) == -1L) {
status = TEXT_FILE_ERROR_READ_FAILED;
} else {
if (!len) {
status = TEXT_FILE_STATUS_EOF;
} else {
fd->fd_CurrentPtr = fd->fd_ReadBuffer;
fd->fd_EndPtr = fd->fd_ReadBuffer + len;
status = TEXT_FILE_STATUS_NORMAL;
}
}
return(status);
}
/* Close text file */
VOID
close_text_file(struct FileData *fd)
{
if (fd && fd->fd_ID == ISUP_ID) {
dos_close(fd->fd_FileHandle);
FreeMem(fd, (LONG)(sizeof(struct FileData) + fd->fd_ReadBufferSize +
fd->fd_LineBufferSize + 1));
}
}
/* DOS calls between open and close of dos library
* -> neccessary for DOS calls from within intuisup.library
*/
#asm
;---------------------------------------------------------------------------
; Support macros
;---------------------------------------------------------------------------
PUSH MACRO
movem.l \1,-(sp)
ENDM
PULL MACRO
movem.l (sp)+,\1
ENDM
CALLSYS MACRO
XREF _LVO\1
jsr _LVO\1(a6)
ENDM
;---------------------------------------------------------------------------
; External definitions
;---------------------------------------------------------------------------
XDEF _dos_open
XDEF _dos_read
XDEF _dos_close
;---------------------------------------------------------------------------
; BPTR dos_open(BYTE *name, LONG flags)
; a0 d0
;---------------------------------------------------------------------------
_dos_open:
PUSH d2-d3/a2/a6
; --- save parameters
move.l a0,a2 ; a2 := file name ptr
move.l d0,d2 ; d2 := flags
moveq #0,d3 ; d3 := return code
; --- open dos library
move.l (4).w,a6 ; a6 := SysBase
lea dos_name(pc),a1 ; a1 := library name
moveq #0,d0 ; d0 := version
CALLSYS OpenLibrary
tst.l d0
beq.s do_exit
; --- call DOS function Open()
move.l d0,a6 ; a6 := DosBase
move.l a2,d1 ; d1 := file name ptr
; d2 := flags
jsr -$1e(a6) ; CALLSYS Open -> Bug in c16.lib (POSITIVE lib offset)
move.l d0,d3 ; d3 := BPTR to file handle
; --- close dos library
move.l a6,a1 ; a1 := DosBase
move.l (4).w,a6 ; a6 := SysBase
CALLSYS CloseLibrary
do_exit:
; --- prepare return code
move.l d3,d0
PULL d2-d3/a2/a6
rts
;---------------------------------------------------------------------------
; LONG dos_read(BPTR fh, BYTE *buffer, LONG size);
; a0 a1 d0
;---------------------------------------------------------------------------
_dos_read:
PUSH d2-d4/a2-a3/a6
; --- save parameters
move.l a0,a2 ; a2 := BPTR to file handle
move.l a1,a3 ; a3 := buffer ptr
move.l d0,d3 ; d3 := size
moveq #-1,d4 ; d4 := return code
; --- open dos library
move.l (4).w,a6 ; a6 := SysBase
lea dos_name(pc),a1 ; a1 := library name
moveq #0,d0 ; d0 := version
CALLSYS OpenLibrary
tst.l d0
beq.s dr_exit
; --- call DOS function Read()
move.l d0,a6 ; a6 := DosBase
move.l a2,d1 ; d1 := BPTR to file handle
move.l a3,d2 ; d2 := buffer ptr
; d3 := size
jsr -$2a(a6) ; CALLSYS Read -> Bug in c16.lib (POSITIVE lib offset)
move.l d0,d4 ; d4 := num of characters read
; --- close dos library
move.l a6,a1 ; a1 := DosBase
move.l (4).w,a6 ; a6 := SysBase
CALLSYS CloseLibrary
dr_exit:
; --- prepare return code
move.l d4,d0
PULL d2-d4/a2-a3/a6
rts
;---------------------------------------------------------------------------
; VOID dos_close(BPTR fh);
; a0
;---------------------------------------------------------------------------
_dos_close:
PUSH a2/a6
; --- save parameters
move.l a0,a2 ; a2 := BPTR to file handle
; --- open dos library
move.l (4).w,a6 ; a6 := SysBase
lea dos_name(pc),a1 ; a1 := library name
moveq #0,d0 ; d0 := version
CALLSYS OpenLibrary
tst.l d0
beq.s dc_exit
; --- call DOS function Close()
move.l d0,a6 ; a6 := DosBase
move.l a2,d1 ; d1 := BPTR to file handle
jsr -$24(a6) ; CALLSYS Close -> Bug in c16.lib (POSITIVE lib offset)
; --- close dos library
move.l a6,a1 ; a1 := DosBase
move.l (4).w,a6 ; a6 := SysBase
CALLSYS CloseLibrary
dc_exit:
PULL a2/a6
rts
;---------------------------------------------------------------------------
; Static data
;---------------------------------------------------------------------------
dos_name:
dc.b "dos.library"
EVEN
#endasm